#coding=utf-8
#LightCam 登录用户监控程序
#init by hfh 20150810

import socket,os,time,re,sys
import lc_libs
import multiprocessing,subprocess,traceback

def write_data(datastr):
	today=time.strftime('%Y%m%d',time.localtime())
	logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
	datafile=open("../data/BASIC/"+today,"a")
	datafile.write(logdate+" "+datastr+"\n")
	datafile.close()

def get_uptime_user(strs):
	res=strs.split(",")
	upyear="0"
	upday="0"
	uphour="0"
	upmin="0"
	loguser="0"
	for line in res:
		tline=line.split()
		length=len(tline)
		if "years" in line:
			upyear=tline[length-2]
		elif "days" in line:
			upday=tline[length-2]
		elif "min" in line:
			upmin=tline[length-2]
		elif re.match("^top.*[0-9][0-9]:[0-9][0-9]$",line):
			templine=tline[length-1]
			tline=templine.split(":")
			uphour=tline[0].strip()
			upmin=tline[1]
		elif re.match(".*[0-9][0-9]:[0-9][0-9]$",line) and "up" not in line:
			tline=line.split(":")
			uphour=tline[0].strip()
			upmin=tline[1]
		elif "users" in line:
			loguser=tline[length-2]
	redata=[upyear,upday,uphour,upmin,loguser]
	return redata
			

if __name__ == "__main__":

	#初始化
	lchome=lc_libs.lc_getlchome()
	scname=sys.argv[0].split('.')[0]
	logfilename=lchome+'/log/'+scname+'.log'
	confname=lchome+'/conf/'+scname+'.conf'
	
	today=time.strftime('%Y%m%d',time.localtime())
	os.system("mv %s %s.%s" % (logfilename,logfilename,today))
	
	logfile=file(logfilename,'a')
	logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
	logfile.write(logdate+" Started.\n")
	logfile.flush()
	
	agent_hostname=lc_libs.lc_gethostname()
	
	#comd = "top -b -n 1|head -20;df|grep ' /'|awk '{print \"DiskUsed \"$NF\" \"$(NF-1)}'"
	comd = "w"
	
	#USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
	#imonitor pts/0    172.25.168.165   03Aug15  2days 13:20m  0.20s -bash
	
	try:
		#初始化数据库
		
		db=lc_libs.lc_mongodb_operater('127.0.0.1',27017)

		db.connect()
		Conn=db.getConn()
		if Conn==None:
			print "Can not Connect to the MondbDB"
			exit(0)
		
		events_dbname='lc_events'
		events_tablename='lc_events'
		
		history_dbname='lc_history'
		history_tablename="lc_onlineuser"
		
		events_db=db.useDatabase(events_dbname)
		events_table=db.UseCollection(events_db,events_tablename)
		
		history_db=db.useDatabase(history_dbname)
		history_table=db.UseCollection(history_db,history_tablename)

	except Exception:
		excinfo=traceback.format_exc()
		logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
		logfile.write(logdate+" 初始化数据库失败:\n"+excinfo+"\n")
		logfile.flush()
		exit(0)
	
	try:
		#初始化配置
		#username:alertgroup,logip,reverse,severity,schedule,holiday
		UserConf = {}
		
		for lines in open(confname):
			if lines[0] == '#' or lines.split("\t")[0] not in (agent_hostname,'default'):
				continue
			line=lines.strip('\r\n').split('\t')
			UserConf[line[2]]={'alertgroup':line[1],'logip':line[3],'reverse':line[4],'severity':line[5],'schedule':line[6],'holiday':line[7]}
	except Exception:
		excinfo=traceback.format_exc()
		logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
		logfile.write(logdate+" 初始化配置文件失败:\n"+excinfo+"\n")
		logfile.flush()
		exit(0)
	
	#设置节点,告警组
	Node=agent_hostname

	#主程序
	while True:
		try:
			popen=subprocess.Popen(comd,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)
			#判断子进程是否结束
			while True:
				if popen.poll()==None:
					time.sleep(0.1)
					continue
				else:
					break
			#处理程序
			for line in popen.stdout.readlines():
				if line[0]==" " or line[:4]=="USER":
					continue
				else:
					lines=line.split()
					v_user=lines[0]
					v_tty=lines[1]
					v_from=lines[2]
					v_login=lines[3]
					v_idle=lines[4]
					v_jcpu=lines[5]
					v_pcpu=lines[6]
					v_what=lines[7]
					
					values="user:%s,tty:%s,from:%s,login:%s,idle:%s,jcpu:%s,pcpu:%s,what:%s\n" % (v_user,v_tty,v_from,v_login,v_idle,v_jcpu,v_pcpu,v_what)
					datas=[
						{"Node":Node,"Name":"OnlineUser","Value":values,"Time":int(time.time())},
						]
					db.insertDatas(history_table,datas)
					
					if v_user in UserConf.keys():
						thisuser=UserConf[v_user]
						#username:alertgroup,logip,reverse,severity,schedule,holiday
						holiday_state = lc_libs.lc_isholiday()
						if int(thisuser['holiday']) == 1 and holiday_state == True:
							continue
						time_state = lc_libs.lc_schedule(thisuser['schedule'])
						if time_state == False:
							continue
						
						AlertGroup=thisuser['alertgroup']
						AlertKey=v_user+"-"+v_from
						Severity=int(thisuser['severity'])
						Type="1"
						
						logips=thisuser['logip'].split('|')
						
						#如果为any,默认都告;如果reverse为1则都不告:
						if thisuser['logip']=='any':
							if int(thisuser['reverse'])==1:
								continue
						#如果指定了IP列表,默认此IP列表中的告,如果reverse为1,则此IP列表中的不告
						elif v_from in logips:
							if int(thisuser['reverse'])==1:
								continue
						
						Summary="%s系统有程序操作用户%s直接登录ip为%s,详细信息:%s" % (Node,v_user,v_from,values)
						strs=lc_libs.lc_gen_alert(agent_hostname,Node,AlertGroup,AlertKey,Severity,Type,Summary)
						print strs
						db.update_eventsdb_rt(events_table,agent_hostname,Node,AlertGroup,AlertKey,Severity,Type,Summary)
					else:
						AlertGroup='OnlineUserKnow'
						AlertKey=v_user+"-"+v_from
						Severity=4
						Type="1"
						Summary="%s系统有未知程序操作用户%s直接登录ip为%s,详细信息:%s" % (Node,v_user,v_from,values)
						strs=lc_libs.lc_gen_alert(agent_hostname,Node,AlertGroup,AlertKey,Severity,Type,Summary)
						print strs
						db.update_eventsdb_rt(events_table,agent_hostname,Node,AlertGroup,AlertKey,Severity,Type,Summary)
				
		except Exception:
			excinfo=traceback.format_exc()
			logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
			logfile.write(logdate+" "+excinfo+"\n")
			logfile.flush()
			time.sleep(1)
		time.sleep(60)
